Fix preemption of multicalls in compat mode.
authorIan Campbell <ian.campbell@xensource.com>
Wed, 30 May 2007 10:55:38 +0000 (11:55 +0100)
committerIan Campbell <ian.campbell@xensource.com>
Wed, 30 May 2007 10:55:38 +0000 (11:55 +0100)
mcs->call (struct multicall_entry) always needs to be translated into
mcs->compat_call (struct compat_multicall_entry) when a multicall is
preempted in compat mode. Previously this translation only occured for
those hypercalls which explicitly called hypercall_xlat_continuation()
which doesn't cover all hypercalls which could potentially be
preempted.

Change hypercall_xlat_continuation() to only translate only the
hypercall arguments themselves and not the multicall_entry
layout. Translate the layout for all hypercalls in in
compat_multicall() instead.

Signed-off-by: Ian Campbell <ian.campbell@xensource.com>
xen/arch/x86/domain.c
xen/common/compat/multicall.c
xen/common/multicall.c

index 281ae7b79314cca8783d5028d1cff5f1c1bf9ec8..085e90d4dab31a2150b6b6d7272bd1c89b480b15 100644 (file)
@@ -1456,13 +1456,12 @@ int hypercall_xlat_continuation(unsigned int *id, unsigned int mask, ...)
                 id = NULL;
             }
             if ( (mask & 1) && mcs->call.args[i] == nval )
-                ++rc;
-            else
             {
-                cval = mcs->call.args[i];
-                BUG_ON(mcs->call.args[i] != cval);
+                mcs->call.args[i] = cval;
+                ++rc;
             }
-            mcs->compat_call.args[i] = cval;
+            else
+                BUG_ON(mcs->call.args[i] != (unsigned int)mcs->call.args[i]);
         }
     }
     else
index 17b12d6462f5cde66cb2c6c366a42e01bce0d55b..0eb12127725bd7258a6eca400469ec608f57035f 100644 (file)
 typedef int ret_t;
 #undef do_multicall_call
 
+static inline void xlat_multicall_entry(struct mc_state *mcs)
+{
+    int i;
+    for (i=0; i<6; i++)
+        mcs->compat_call.args[i] = mcs->call.args[i];
+}
+
 DEFINE_XEN_GUEST_HANDLE(multicall_entry_compat_t);
 #define multicall_entry      compat_multicall_entry
 #define multicall_entry_t    multicall_entry_compat_t
index c03002256e0c7927b110a6d0fb27f979f6278945..7ee21b47c12e1427c24ae373d044daf5448b9e6f 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef COMPAT
 DEFINE_PER_CPU(struct mc_state, mc_state);
 typedef long ret_t;
+#define xlat_multicall_entry(mcs)
 #endif
 
 ret_t
@@ -62,6 +63,9 @@ do_multicall(
 
         if ( test_bit(_MCSF_call_preempted, &mcs->flags) )
         {
+            /* Translate sub-call continuation to guest layout */
+            xlat_multicall_entry(mcs);
+
             /* Copy the sub-call continuation. */
             (void)__copy_to_guest(call_list, &mcs->call, 1);
             goto preempted;